/*
 * interface.h
 *
 *  Created on: 13/09/2011
 *      Author: OIM
 */

#ifndef INTERFACE_H_
#define INTERFACE_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/un.h>
#include <semaphore.h>
#include "logfile.h"

typedef struct
{
        unsigned char ID[16];
        unsigned char Tipo;
        int16_t Length;
        int32_t Sector;
        unsigned char* Datos;
} Paquete;

typedef unsigned char sector[512];

typedef sector tipoBloque[2];

typedef struct nodoSocket
{
	int32_t sock;
	int32_t libre;
	struct nodoSocket* sgte;
}tipoSocket;

typedef struct nodoPedido
{
	unsigned char ID[16];
	int32_t bloque;
	int32_t sector;
	struct nodoPedido* sgte;
}tipoPedido;

#define secPerBlock 2
#define secSize 512
#define buffer 2048

#define SERVER_PATH		"/tmp/archivosock"
#define BUFFER_LENGTH    276
//#define SUN_LEN(su)  (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#define MYPORT 4000		/*	Puerto al que conectara FUSE	*/
#define BACKLOG 10		/*	Cu�ntas conexiones pendientes se mantienen en cola	*/

#define BUFFER_MAX 535
#define HANDSHAKE_CONSOLE 0x32
#define HANDSHAKE_PPD '0'
#define HANDSHAKE_OK 0x23
#define SYS_INFO 0x35
#define DATA_INFO 0x36
#define GET_BLOCK 0x37
#define PUT_BLOCK 0x38
#define GET_SECTOR 'L'
#define PUT_SECTOR 'E'
#define GET_BOOT 0x41
#define GET_FAT 0x42
#define PUT_FAT 0x43

tipoSocket* listaSockets;
int32_t blockPerCluster;

pthread_mutex_t mutex_oper_fat;
pthread_mutex_t mutex_cacheDirectorio;
pthread_mutex_t mutex_cacheFile;
sem_t semAtendidos;
sem_t semPedidos;
sem_t semSockets;
pthread_mutex_t mutexPedidos;
pthread_mutex_t mutexAtendidos;

pthread_mutex_t mutexSockets;

int32_t conexionLibre();
void liberarConexion( int32_t sock );
void agregarConexion( int32_t sock );
int32_t crearPoolConexiones(  int32_t maxConex );
tipoPedido* agregarPedido( unsigned char ID[16], int32_t bloque, int32_t sector, tipoPedido* listaPedidoLocal );
unsigned char* getBootSector(int32_t clusterID, int32_t initSector);
unsigned char* getFatRegion(int32_t reserveSize, int32_t fatSize);
int32_t putFATRegion(int32_t initSector, int32_t totalFatSize, unsigned char* data);
int32_t getSector(int32_t socketPD, int32_t sectorNumber, int32_t flag);
int32_t putSector(int32_t socketPD, unsigned char *data, int32_t sectorNumber);
int32_t getBlock(int32_t socketPD, int32_t blockNumber, int32_t sectorNumber, unsigned char IDMsj[16]);
int32_t putBlock(int32_t socketPD, unsigned char* data, int32_t initSector);

unsigned char* getCluster(int32_t clusterID, int32_t initSector);
int32_t putCluster(int32_t clusterID, int32_t initSector, unsigned char* data);
void set_blockPerCluster(int32_t sectoresPerCluster);
void* revisarPedidos(void* args);
int32_t sonDistintos( unsigned char ID[16], unsigned char otroID[16] );

#endif /* INTERFACE_H_ */
